package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"sysinfo/internal/analyzer"
	"sysinfo/internal/collector"
	"sysinfo/internal/config"
	"sysinfo/internal/types"

	"github.com/spf13/cobra"
)

var (
	smartPeriod string
	smartDBPath string
)

// smartCmd 表示smart命令
var smartCmd = &cobra.Command{
	Use:   "smart",
	Short: "SMART磁盘健康监控和分析",
	Long: `高级SMART磁盘健康监控，具有预测性故障检测、
历史跟踪和警报功能。

示例:
  sysinfo smart analyze              # 分析所有驱动器并预测故障
  sysinfo smart history              # 显示7天趋势历史
  sysinfo smart history --period 30d # 显示30天趋势
  sysinfo smart check                # 快速检查所有驱动器健康状态`,
}

// smartAnalyzeCmd 执行深度SMART分析
var smartAnalyzeCmd = &cobra.Command{
	Use:   "analyze",
	Short: "执行深度SMART分析和故障预测",
	Long: `分析所有驱动器的SMART数据并提供:
  - 健康状态分类
  - 预测性故障检测和概率
  - SSD磨损分析和寿命估算
  - 温度监控
  - 详细建议

结果会自动存储到历史数据库中。`,
	RunE: runSmartAnalyze,
}

// smartHistoryCmd 显示历史SMART数据
var smartHistoryCmd = &cobra.Command{
	Use:   "history",
	Short: "显示SMART历史和趋势",
	Long: `显示历史SMART数据和趋势分析，包括:
  - 最近的健康记录
  - 温度趋势（上升/稳定/下降）
  - 健康状态趋势
  - SSD磨损率和预计寿命终止日期`,
	RunE: runSmartHistory,
}

// smartCheckCmd 执行快速健康检查
var smartCheckCmd = &cobra.Command{
	Use:   "check",
	Short: "快速SMART健康检查",
	Long: `对所有驱动器执行快速健康检查，不存储到历史记录。
适用于脚本和监控系统。`,
	RunE: runSmartCheck,
}

func init() {
	// 添加smart命令到根命令
	rootCmd.AddCommand(smartCmd)

	// 添加子命令
	smartCmd.AddCommand(smartAnalyzeCmd)
	smartCmd.AddCommand(smartHistoryCmd)
	smartCmd.AddCommand(smartCheckCmd)

	// 所有smart子命令的共享标志
	smartCmd.PersistentFlags().StringVar(&smartDBPath, "db", "", "自定义数据库路径 (默认: 二进制文件旁边的smart.db)")
	smartCmd.PersistentFlags().BoolVarP(&cfg.Verbose, "verbose", "v", false, "详细输出")

	// 历史记录特定标志
	smartHistoryCmd.Flags().StringVar(&smartPeriod, "period", "7d", "时间段 (例如: 1h, 24h, 7d, 30d)")

	// 分析特定标志
	smartAnalyzeCmd.Flags().BoolVar(&cfg.SMARTAlerts, "alerts", false, "为关键问题发送webhook警报")
}

func runSmartAnalyze(cmd *cobra.Command, args []string) error {
	if cfg.Verbose {
		fmt.Fprintf(os.Stderr, "正在初始化SMART分析...\n")
	}

	// 设置数据库
	db, fileConfig, err := initSMARTDatabase()
	if err != nil {
		return err
	}
	defer db.Close()

	// 设置分析器
	smartAnalyzer := createAnalyzer(fileConfig)

	// 如果启用则设置警报
	var alertMgr *analyzer.AlertManager
	if cfg.SMARTAlerts {
		alertMgr = createAlertManager(fileConfig)
	}

	// 收集SMART数据
	diskData, err := collectSMARTData()
	if err != nil {
		return err
	}

	if len(diskData.SMARTData) == 0 {
		fmt.Fprintf(os.Stderr, "没有可用的SMART数据。请尝试使用提升的权限运行（sudo）。\n")
		return nil
	}

	// 分析每个驱动器
	for _, smart := range diskData.SMARTData {
		if cfg.Verbose {
			fmt.Fprintf(os.Stderr, "正在分析 %s...\n", smart.Device)
		}

		result := smartAnalyzer.Analyze(&smart)

		// 存储到历史记录
		if err := db.RecordAnalysis(&smart, result); err != nil {
			fmt.Fprintf(os.Stderr, "警告：为 %s 记录历史失败：%v\n", smart.Device, err)
		}

		// 发送警报
		if alertMgr != nil {
			if err := alertMgr.CheckAndAlert(result); err != nil {
				fmt.Fprintf(os.Stderr, "警告：为 %s 发送警报失败：%v\n", smart.Device, err)
			}
		}

		// 显示结果
		displayAnalysisResult(result)
	}

	return nil
}

func runSmartHistory(cmd *cobra.Command, args []string) error {
	// 设置数据库
	db, _, err := initSMARTDatabase()
	if err != nil {
		return err
	}
	defer db.Close()

	// 解析时间段
	period, err := parseDuration(smartPeriod)
	if err != nil {
		return fmt.Errorf("时间段格式无效：%w", err)
	}

	since := time.Now().Add(-period)

	// 获取所有设备
	devices, err := db.GetDevices()
	if err != nil {
		return fmt.Errorf("获取设备失败：%w", err)
	}

	if len(devices) == 0 {
		fmt.Println("没有可用的SMART历史数据。")
		fmt.Println("\n运行 'sysinfo smart analyze' 开始收集数据。")
		return nil
	}

	// 显示标题
	fmt.Printf("SMART历史记录（最近 %s）\n", smartPeriod)
	fmt.Println(repeatString("=", 70))

	// 显示每个设备的历史
	for _, device := range devices {
		if err := displayDeviceHistory(db, device, since); err != nil {
			fmt.Fprintf(os.Stderr, "显示 %s 历史时出错：%v\n", device, err)
			continue
		}
	}

	return nil
}

func runSmartCheck(cmd *cobra.Command, args []string) error {
	if cfg.Verbose {
		fmt.Fprintf(os.Stderr, "正在执行SMART健康检查...\n")
	}

	// 收集SMART数据
	diskData, err := collectSMARTData()
	if err != nil {
		return err
	}

	if len(diskData.SMARTData) == 0 {
		fmt.Fprintf(os.Stderr, "没有可用的SMART数据。请尝试使用提升的权限运行（sudo）。\n")
		return nil
	}

	// 快速分析，不存储
	smartAnalyzer := analyzer.NewSMARTAnalyzer()

	allHealthy := true
	for _, smart := range diskData.SMARTData {
		result := smartAnalyzer.Analyze(&smart)

		status := "✓"
		switch result.OverallHealth {
		case analyzer.HealthCritical, analyzer.HealthFailing:
			status = "✗"
			allHealthy = false
		case analyzer.HealthWarning:
			status = "⚠"
			allHealthy = false
		}

		fmt.Printf("%s %-20s %s", status, smart.Device, result.OverallHealth)

		if result.PredictedFailure {
			fmt.Printf("  [预测故障：%.1f%%]", result.FailureProbability)
		} else if result.FailureProbability > 20 {
			fmt.Printf("  [风险：%.1f%%]", result.FailureProbability)
		}

		if result.SSDWearAnalysis != nil && result.SSDWearAnalysis.RemainingLife < 20 {
			fmt.Printf("  [SSD寿命：%.1f%%]", result.SSDWearAnalysis.RemainingLife)
		}

		fmt.Println()
	}

	if allHealthy {
		fmt.Println("\n✓ 所有驱动器健康")
		return nil
	}

	fmt.Println("\n⚠ 检测到问题 - 运行 'sysinfo smart analyze' 查看详情")
	return nil
}

// 辅助函数

func initSMARTDatabase() (*analyzer.HistoryDB, *config.FileConfig, error) {
	// 加载配置文件
	fileConfig, _ := config.LoadConfigFile(configFile)

	// 确定数据库路径
	dbPath := smartDBPath
	if dbPath == "" && fileConfig != nil {
		dbPath = fileConfig.SMART.DBPath
	}
	if dbPath == "" {
		// 默认将数据库放在二进制文件旁边（支持多操作系统）
		exePath, err := os.Executable()
		if err != nil {
			return nil, nil, fmt.Errorf("获取可执行文件路径失败：%w", err)
		}
		exeDir := filepath.Dir(exePath)
		dbPath = filepath.Join(exeDir, "smart.db")
	}

	// 确保目录存在
	dbDir := filepath.Dir(dbPath)
	if err := os.MkdirAll(dbDir, 0755); err != nil {
		return nil, nil, fmt.Errorf("创建数据库目录失败：%w", err)
	}

	// 打开数据库
	db, err := analyzer.NewHistoryDB(dbPath)
	if err != nil {
		return nil, nil, fmt.Errorf("打开SMART历史数据库失败：%w", err)
	}

	return db, fileConfig, nil
}

func createAnalyzer(fileConfig *config.FileConfig) *analyzer.SMARTAnalyzer {
	if fileConfig != nil && fileConfig.SMART.AlertThresholds.TemperatureCritical > 0 {
		return analyzer.NewSMARTAnalyzerWithConfig(analyzer.AnalyzerConfig{
			TempWarning:      fileConfig.SMART.AlertThresholds.TemperatureWarning,
			TempCritical:     fileConfig.SMART.AlertThresholds.TemperatureCritical,
			WearWarning:      80.0,
			WearCritical:     90.0,
			EnablePredictive: true,
		})
	}
	return analyzer.NewSMARTAnalyzer()
}

func createAlertManager(fileConfig *config.FileConfig) *analyzer.AlertManager {
	webhookURL := ""
	if fileConfig != nil {
		webhookURL = fileConfig.SMART.WebhookURL
	}

	if webhookURL == "" && cfg.Verbose {
		fmt.Fprintf(os.Stderr, "警告：已启用警报但未配置webhook URL\n")
		fmt.Fprintf(os.Stderr, "在配置文件的smart部分添加'webhook_url'\n")
	}

	return analyzer.NewAlertManager(analyzer.AlertConfig{
		Enabled:        true,
		WebhookURL:     webhookURL,
		WebhookTimeout: 30,
		MinLevel:       analyzer.AlertWarning,
		Cooldown:       60,
	})
}

func collectSMARTData() (*types.DiskData, error) {
	if cfg.Verbose {
		fmt.Fprintf(os.Stderr, "正在收集SMART数据...\n")
	}

	diskData, err := collector.CollectDisk(true)
	if err != nil {
		return nil, fmt.Errorf("收集磁盘数据失败：%w", err)
	}

	return diskData, nil
}

func displayDeviceHistory(db *analyzer.HistoryDB, device string, since time.Time) error {
	fmt.Printf("\n设备：%s\n", device)
	fmt.Println(repeatString("-", 70))

	// 获取历史记录
	history, err := db.GetHistory(device, since, 100)
	if err != nil {
		return fmt.Errorf("获取历史失败：%w", err)
	}

	if len(history) == 0 {
		fmt.Println("  此期间无记录")
		return nil
	}

	// 显示最近记录
	fmt.Printf("  最近记录：%d\n", len(history))
	maxRecords := 5
	if len(history) < maxRecords {
		maxRecords = len(history)
	}

	for i := 0; i < maxRecords; i++ {
		record := history[i]
		fmt.Printf("    %s | 健康：%-8s | 温度：%3d°C | 问题：%d（严重：%d）\n",
			record.Timestamp.Format("2006-01-02 15:04"),
			record.HealthStatus,
			record.Temperature,
			record.IssueCount,
			record.CriticalIssues,
		)
	}

	// 获取趋势分析
	trend, err := db.GetTrend(device, since)
	if err != nil {
		return fmt.Errorf("计算趋势失败：%w", err)
	}

	fmt.Println("\n  趋势：")
	fmt.Printf("    温度：%s（平均：%.1f°C，最低：%d°C，最高：%d°C）\n",
		trend.TempTrend, trend.AvgTemperature, trend.MinTemperature, trend.MaxTemperature)
	fmt.Printf("    健康状态：%s\n", trend.HealthTrend)

	if trend.SSDWearRate > 0 {
		fmt.Printf("    SSD磨损率：每天%.4f%%\n", trend.SSDWearRate)
		if trend.EstimatedFailureDate != nil {
			fmt.Printf("    预计寿命终止：%s\n",
				trend.EstimatedFailureDate.Format("2006-01-02"))
		}
	}

	return nil
}

func displayAnalysisResult(result *analyzer.AnalysisResult) {
	fmt.Printf("\n%s\n", result.Device)
	fmt.Println(repeatString("=", 70))

	// 整体健康
	healthSymbol := getHealthSymbol(result.OverallHealth)
	fmt.Printf("整体健康：%s %s\n", healthSymbol, result.OverallHealth)

	// 预测分析
	if result.PredictedFailure {
		fmt.Printf("⚠ 预测故障（%.1f%%概率）\n", result.FailureProbability)
	} else if result.FailureProbability > 20 {
		fmt.Printf("故障风险：%.1f%%\n", result.FailureProbability)
	}

	// SSD磨损分析
	if result.SSDWearAnalysis != nil {
		displaySSDWear(result.SSDWearAnalysis)
	}

	// 问题
	if len(result.Issues) > 0 {
		displayIssues(result.Issues)
	}

	// 建议
	if len(result.Recommendations) > 0 {
		displayRecommendations(result.Recommendations)
	}

	fmt.Println()
}

func getHealthSymbol(health analyzer.HealthStatus) string {
	switch health {
	case analyzer.HealthGood:
		return "✓"
	case analyzer.HealthWarning:
		return "⚠"
	case analyzer.HealthCritical, analyzer.HealthFailing:
		return "✗"
	default:
		return "?"
	}
}

func displaySSDWear(wear *analyzer.SSDWearInfo) {
	fmt.Println("\nSSD磨损分析：")
	fmt.Printf("  状态：%s\n", wear.WearStatus)
	fmt.Printf("  剩余寿命：%.1f%%\n", wear.RemainingLife)
	fmt.Printf("  已使用：%.1f%%\n", wear.PercentUsed)
	if wear.EstimatedLifespan > 0 {
		days := int(wear.EstimatedLifespan.Hours() / 24)
		years := float64(days) / 365.0
		fmt.Printf("  预计剩余：%d天（%.1f年）\n", days, years)
	}
}

func displayIssues(issues []analyzer.Issue) {
	fmt.Printf("\n发现问题：%d\n", len(issues))
	for _, issue := range issues {
		var severity string
		switch issue.Severity {
		case analyzer.SeverityCritical:
			severity = "严重"
		case analyzer.SeverityWarning:
			severity = "警告"
		default:
			severity = "信息"
		}
		fmt.Printf("  [%s] %s\n", severity, issue.Description)
	}
}

func displayRecommendations(recommendations []string) {
	fmt.Println("\n建议：")
	for _, rec := range recommendations {
		fmt.Printf("  • %s\n", rec)
	}
}

func parseDuration(s string) (time.Duration, error) {
	if len(s) < 2 {
		return 0, fmt.Errorf("时间段格式无效")
	}

	unit := s[len(s)-1]
	value := s[:len(s)-1]

	var multiplier time.Duration
	switch unit {
	case 'h':
		multiplier = time.Hour
	case 'd':
		multiplier = 24 * time.Hour
	case 'w':
		multiplier = 7 * 24 * time.Hour
	case 'm':
		multiplier = 30 * 24 * time.Hour
	default:
		return time.ParseDuration(s)
	}

	var num int
	if _, err := fmt.Sscanf(value, "%d", &num); err != nil {
		return 0, fmt.Errorf("时间段中的数字无效：%w", err)
	}

	return time.Duration(num) * multiplier, nil
}

func repeatString(s string, n int) string {
	result := ""
	for i := 0; i < n; i++ {
		result += s
	}
	return result
}
